package com.vodafone.nocs.inops.tools.test.ldap;

import java.util.Collections;
import java.util.Enumeration;
import java.util.GregorianCalendar;
import java.util.LinkedList;
import java.util.Queue;

import netscape.ldap.LDAPAttribute;
import netscape.ldap.LDAPAttributeSet;
import netscape.ldap.LDAPEntry;
import netscape.ldap.LDAPException;
import netscape.ldap.LDAPInterruptedException;
import netscape.ldap.LDAPReferralException;
import netscape.ldap.LDAPSearchResults;

public class Jdispatcher {
	
	private static LdapWrapper ldse;
	
	static PROCQUE2 ProcessingQueue = new PROCQUE2();

	static IdThread t[] = new IdThread[10];
	static IdThread mon = new IdThread(new Monitor());

	static long[] waitTime = new long[10];
	
	private static class PROCQUEX {

		Queue<String[]> queue = new LinkedList<String[]>();

		public synchronized void put(String[] message) {
			queue.add(message);
			notify();
		}

		public synchronized String[] get() {
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return queue.poll();
		}

	}
	private static class PROCQUE2 {

		Queue<String[]> queue = new LinkedList<String[]>();

		public void put(String[] message) {
			synchronized(this){
				queue.add(message);
				notify();
			}
		}

		public synchronized String[] get() {
			synchronized(this){
				if (queue.isEmpty()){
					try {
						wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				return queue.poll();	
			}
		}
	}


	private static class Worker implements Runnable {
		public void run() {
			while (true) {
				String[] message = ProcessingQueue.get();
				parse(message);
			}
		}
	};
	
	private static class Monitor implements Runnable {
		public void run() {
			while (true) {
				// check blocked threads and unblock them
				try {
					Thread.sleep(10000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				GregorianCalendar cal = new GregorianCalendar(2007, 9 - 1, 23);
				long ref = cal.getTimeInMillis();
				for (int i = 0 ; i < 10; i ++){
					OUTLOG("waitme "+ i + " : " + waitTime[i]);
					if (waitTime[i] != 0 && waitTime[i] < ref - 20000){
						OUTLOG( i +" seems hanged " + (ref - waitTime[i]));
						t[i].interrupt();
					}
				}
			}
		}
	};


	public static void parse(String[] filter) {
			
		String[] ATTRS = { "cn", "mail", "telephonenumber" };
		
		GregorianCalendar cal = new GregorianCalendar(2007, 9 - 1, 23);
		IdThread _current = (IdThread) Thread.currentThread();
		int i = _current.getThreadId();
		if (filter.length == 2)
			OUTLOG(" COMMAND \ninin " + filter[0] +"\ninin "+ filter[1]);
		else
			OUTLOG(" COMMAND \ninin " + filter[0]);

		
		waitTime[i] = cal.getTimeInMillis();
		String command =  new String();
		try {
			for (String _command : filter){
				
				command = _command;
				
				//OUTLOG(" INSTRUCTION " + _command);
				
				long millis = cal.getTimeInMillis();
				
				LDAPSearchResults res = ldse.getLd().search(ldse.getBase(), ldse.getLd().SCOPE_ONE, _command,
						ATTRS, false);
				
				while (res.hasMoreElements()) {
					try {
						// The next entry
						LDAPEntry entry = res.next();
						printEntry(entry, ATTRS);
					} catch (LDAPReferralException e) {
						// Ignore any referrals
						continue;
					} 
				}

			}
		} catch (Exception e){
			OUTLOG("REJECTED COMMAND\nerer "+command+"\n--");

			
			if (e.getMessage().compareTo("bundle error!!") == 0){
				
			}else{
				if (!ldse.getLd().isConnected()){
					OUTLOG(" reconnecting " + filter[0]);

					ldse.connectLdap();
				}
				
				//requeue
				ProcessingQueue.put(filter);

			}
			waitTime[i] = 0;
			return;
			
		} 
		if (filter.length == 2)
			OUTLOG(" EXECUTED \nokok " + filter[0] +"\nokok "+ filter[1]);
		else
			OUTLOG(" EXECUTED \nokok " + filter[0]);
		
		waitTime[i] = 0;
		return;
		
	}

	public void p_w(String[] message) {
		ProcessingQueue.put(message);
	}

	public static void printEntry(LDAPEntry entry, String[] attrs) throws LDAPException{

		//OUTLOG("DN: " + entry.getDN());

		for (int i = 0; i < attrs.length; i++) {
			LDAPAttribute attr = entry.getAttribute(attrs[i]);
			
			if (attr == null) {
				continue;
			}

			Enumeration enumVals = attr.getStringValues();
			boolean hasVals = false;
			boolean fault = false;
			while ((enumVals != null) && (enumVals.hasMoreElements())) {
				String val = (String) enumVals.nextElement();
				OUTLOG("(2) [" + attrs[i] + ": " + val + "]");
				fault = attrs[i].compareTo("res") == 0 && val.compareTo("00") != 0;
				hasVals = true;
			}
			if (!hasVals) {
				//System.out.println("    [" + attrs[i] + ": has no values]");
			}
			if (fault){
				OUTLOG("ERROR (1)" + entry.getDN());
				throw new LDAPException("bundle error!!"); 
			}
		}

		//System.out.println();
		//System.out.println("  Iterate through all attributes using getAttributes()");

		LDAPAttributeSet entryAttrs = entry.getAttributeSet();
		//System.out.println("  Found " + entryAttrs.size() + " attributes.");
		Enumeration attrEnum = entryAttrs.getAttributes();
		while ((attrEnum != null) && (attrEnum.hasMoreElements())) {

			// Get the attribute
			LDAPAttribute attr = (LDAPAttribute) attrEnum.nextElement();

			if (attr == null) {
				//System.out.println("    [" + attr.getName() + ": not present]");
				continue;
			}

			Enumeration enumVals = attr.getStringValues();
			boolean hasVals = false;
			boolean fault = false;
			while ((enumVals != null) && (enumVals.hasMoreElements())) {
				String val = (String) enumVals.nextElement();
				OUTLOG("(1) [" + attr.getName() + ": " + val + "]");
				fault = attr.getName().compareTo("res") == 0 && val.compareTo("00") != 0;
				hasVals = true;
			}
			if (!hasVals) {
				//System.out.println("    [" + attr.getName()
				//		+ ": has no values]");
			}
			if (fault){
				OUTLOG("ERROR (2)" + entry.getDN());
				throw new LDAPException("bundle error!!"); 
			}

		}

		//System.out.println("---------------------------------------------");
	}
	

	Jdispatcher(LdapWrapper _ldap) {

		for (int i = 0; i < 10; i++) {
			t[i] = new IdThread(new Worker());
			t[i].start();
			t[i].setThreadId(i);
		}
		
		mon.setThreadId(11);
		mon.start();
		
		ldse = _ldap;

	}
	
	public static void OUTLOG(Object string) {
		IdThread _current = (IdThread) Thread.currentThread();
		int i = _current.getThreadId();

		System.out.println(">> Thread " + i + " << ["+string.toString()+"]");	
	}


}
